package doyouknow.group.CnAndZhb.utils;

import com.alibaba.fastjson.JSON;
import doyouknow.group.CnAndZhb.response.BaseControllerReturn;
import doyouknow.group.CnAndZhb.response.CommonReturnType;
import doyouknow.group.CnAndZhb.response.LayuiTableReturnType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by a10.13.6 on 2019/4/29.
 */
@Order(1)
@ControllerAdvice(basePackages = "doyouknow.group.CnAndZhb.controller")
public class MyResponseBodyAdvice implements ResponseBodyAdvice{

    private Logger logger = LoggerFactory.getLogger(getClass());
    //包含项
    private String[] includes = {};
    //排除项
    private String[] excludes = {};
    //是否加密
    private boolean encode = true;
    private int returntype = 0;
    private boolean enable = true;

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(@Nullable Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        //重新初始化为默认值
        includes = new String[]{};
        excludes = new String[]{};
        encode = true;


        //判断返回的对象是单个对象，还是list，活着是map
        if(o==null){
            return null;
        }
        if(methodParameter.getMethod().isAnnotationPresent(SerializedField.class)){
            //获取注解配置的包含和去除字段
            SerializedField serializedField = methodParameter.getMethodAnnotation(SerializedField.class);
            includes = serializedField.includes();
            excludes = serializedField.excludes();
            //是否加密
            encode = serializedField.encode();
            returntype = serializedField.returntype();
            enable = serializedField.enable();
        }


        //如果是已经封装好了的 CommonReturnType 那就是捕获到了  异常
        if (o instanceof CommonReturnType) {
            return o;
        }

        System.out.println("0000000000000000000" + o.toString());
        Object retObj = ((BaseControllerReturn)o).getData();
        Map<String,Object> dataInfo = ((BaseControllerReturn)o).getExtend();


        if(enable){
            if (retObj instanceof List){
                //List
                List list = (List)retObj;
                retObj = handleList(list);
            }else{
                //Single Object
                retObj = handleSingleObject(retObj);
            }
        }

        if(returntype == 1){
            retObj = CommonReturnType.create(retObj);
        }
        if(returntype == 2){
            retObj = LayuiTableReturnType.create(retObj,0, (Long) dataInfo.get("count"),"");
        }
        if(returntype == 3){
            retObj = ((BaseControllerReturn) o).getData();
        }

        logger.info("\n\n响应：{}",JSON.toJSONString(retObj));
//        System.out.println("------------------------------------------------------------------------------------------------------------------");
        return retObj;
    }

    /**
     * 处理返回值是单个enity对象
     *
     * @param o
     * @return
     */
    private Object handleSingleObject(Object o){
        Map<String,Object> map = new HashMap<String, Object>();

        Field[] fields = o.getClass().getDeclaredFields();
        for (Field field:fields){
            //如果未配置表示全部的都返回
            if(includes.length==0 && excludes.length==0){
                String newVal = getNewVal(o, field);
                map.put(field.getName(), newVal);
            }else if(includes.length>0){
                //有限考虑包含字段
                if(Helper.isStringInArray(field.getName(), includes)){

                    Object newVal = null;
                    if("tbPoints".equals(field.getName())){

                        try {
                            field.setAccessible(true);
                            newVal = field.get(o);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }


                    }else {
                        newVal = getNewVal(o, field);
                    }
                    map.put(field.getName(), newVal);
                }
            }else{
                //去除字段
                if(excludes.length>0){
                    if(!Helper.isStringInArray(field.getName(), excludes)){
                        String newVal = getNewVal(o, field);
                        map.put(field.getName(), newVal);
                    }
                }
            }

        }
        return map;
    }

    /**
     * 处理返回值是列表
     *
     * @param list
     * @return
     */
    private List handleList(List list){
        List retList = new ArrayList();
        for (Object o:list){
            Map map = (Map) handleSingleObject(o);
            retList.add(map);
        }
        return retList;
    }

    /**
     * 获取加密后的新值
     *
     * @param o
     * @param field
     * @return
     */
    private String getNewVal(Object o, Field field){
        String newVal = "";
        try {
            field.setAccessible(true);
            Object val = field.get(o);

            if(val!=null){
                if(encode){
                    newVal = Helper.encode(val.toString());
                }else{
                    newVal = val.toString();
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return newVal;
    }

}
